package com.qiguliuxing.dts.wx.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.qiguliuxing.dts.common.constant.CommConsts;
import com.qiguliuxing.dts.common.type.UserTypeEnum;
import com.qiguliuxing.dts.common.util.CharUtils;
import com.qiguliuxing.dts.common.util.IpUtils;
import com.qiguliuxing.dts.common.util.RegexUtils;
import com.qiguliuxing.dts.common.util.ResponseUtils;
import com.qiguliuxing.dts.common.util.bcrypt.BCryptPasswordEncoder;
import com.qiguliuxing.dts.core.annotation.LoginUser;
import com.qiguliuxing.dts.core.annotation.aoplog.WebLog;
import com.qiguliuxing.dts.core.captcha.CaptchaCodeManager;
import com.qiguliuxing.dts.core.manager.UserToken;
import com.qiguliuxing.dts.core.manager.UserTokenManager;
import com.qiguliuxing.dts.core.notify.NotifyType;
import com.qiguliuxing.dts.core.notify.SmsResult;
import com.qiguliuxing.dts.core.support.JacksonUtil;
import com.qiguliuxing.dts.db.domain.DtsUser;
import com.qiguliuxing.dts.db.domain.DtsUserAccount;
import com.qiguliuxing.dts.service.base.CouponAssignService;
import com.qiguliuxing.dts.service.base.DtsAccountService;
import com.qiguliuxing.dts.service.base.DtsUserService;
import com.qiguliuxing.dts.service.notify.NotifyService;
import com.qiguliuxing.dts.service.qcode.QCodeService;
import com.qiguliuxing.dts.service.system.SystemConfig;
import com.qiguliuxing.dts.wx.support.WxResponseUtils;
import com.qiguliuxing.dts.wx.vo.UserInfo;
import com.qiguliuxing.dts.wx.vo.WxLoginInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.qiguliuxing.dts.wx.support.WxResponseCode.*;

/**
 * 鉴权服务
 */
@RestController
@RequestMapping("/wx/auth")
@Validated
@Api(tags = "鉴权服务")
public class WxAuthController {
    private static final Logger logger = LoggerFactory.getLogger(WxAuthController.class);

    @Autowired
    private DtsUserService userService;

    @Autowired
    private WxMaService wxService;

    @Autowired
    private NotifyService notifyService;

    @Autowired
    private CouponAssignService couponAssignService;

    @Autowired
    private DtsAccountService accountService;

    @Autowired
    private QCodeService qCodeService;

    /**
     * 账号登录
     *
     * @param body    请求内容，{ username: xxx, password: xxx }
     * @param request 请求对象
     * @return 登录结果
     */
    @PostMapping("login")
    @ApiOperation(value = "账号登录")
    public Object login(@ApiParam(value = "{ username: xxx, password: xxx }") @RequestBody String body, HttpServletRequest request) {
        String username = JacksonUtil.parseString(body, "username");
        String password = JacksonUtil.parseString(body, "password");
        if (username == null || password == null) {
            return ResponseUtils.badArgument();
        }

        List<DtsUser> userList = userService.queryByUsername(username);
        DtsUser user = null;
        if (userList.size() > 1) {
            logger.error("账户登录 出现多个同名用户错误,用户名:{},用户数量:{}", username, userList.size());
            return ResponseUtils.serious();
        } else if (userList.size() == 0) {
            logger.error("账户登录 用户尚未存在,用户名:{}", username);
            return ResponseUtils.badArgumentValue();
        } else {
            user = userList.get(0);
        }

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(password, user.getPassword())) {
            logger.error("账户登录 ,错误密码：{},{}", password, AUTH_INVALID_ACCOUNT.desc());// 错误的密码打印到日志中作为提示也无妨
            return WxResponseUtils.fail(AUTH_INVALID_ACCOUNT);
        }

        // userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setNickName(username);
        userInfo.setAvatarUrl(user.getAvatar());

        try {
            String registerDate = new SimpleDateFormat("yyyy-MM-dd")
                    .format(user.getAddTime() == null ? user.getAddTime() : LocalDateTime.now());
            userInfo.setRegisterDate(registerDate);
            userInfo.setStatus(user.getStatus());
            userInfo.setUserLevel(user.getUserLevel());// 用户层级
            userInfo.setUserLevelDesc(UserTypeEnum.getInstance(user.getUserLevel()).getDesc());// 用户层级描述
        } catch (Exception e) {
            logger.error("账户登录：设置用户指定信息出错：" + e.getMessage());
            e.printStackTrace();
        }

        // token
        UserToken userToken;
        try {
            userToken = UserTokenManager.generateToken(user.getId(), null);
        } catch (Exception e) {
            logger.error("账户登录失败,生成token失败：{}", user.getId());
            e.printStackTrace();
            return ResponseUtils.fail();
        }
        return getUserAndTokenInfo(userInfo, userToken);
    }

    private Object getUserAndTokenInfo(UserInfo userInfo, UserToken userToken) {
        Map<Object, Object> result = Maps.newHashMap();
        result.put("token", userToken.getToken());
        result.put("tokenExpire", userToken.getExpireTime().toString());
        result.put("userInfo", userInfo);
        return ResponseUtils.ok(result);
    }

    @PostMapping("jsapi")
    @ApiOperation(value = "微信鉴权")
    public Object jspai(@RequestBody Map map) throws WxErrorException {
       return ResponseUtils.ok(wxService.getJsapiService().createJsapiSignature(map.get("url")+""));
    }


    /**
     * 微信登录
     *
     * @param wxLoginInfo 请求内容，{ code: xxx, userInfo: xxx }
     * @param request     请求对象
     * @return 登录结果
     */

    @PostMapping("h5_login")
    @ApiOperation(value = "微信公众号登录")
    public Object loginByH5(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) throws WxErrorException, UnsupportedEncodingException {
        UserInfo userInfo=new UserInfo();
        String openId="";
        String strAppId = wxService.getWxMaConfig().getAppid();
        String strSecret = wxService.getWxMaConfig().getSecret();
        String strUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
        strUrl += "?appid=" + strAppId;
        strUrl += "&secret=" + strSecret;
        strUrl += "&code=" + wxLoginInfo.getCode();
        strUrl += "&grant_type=authorization_code";
        byte[] res = null;
        byte[] res1 = null;

        org.apache.http.client.HttpClient httpclient = new DefaultHttpClient();
        HttpGet httpget = new HttpGet();
        try {
            URL url = new URL(strUrl);
            URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);
            httpget = new HttpGet(uri);
            HttpResponse response = null;
            response = httpclient.execute(httpget);
            res = IOUtils.toByteArray(response.getEntity().getContent());
        } catch (Exception e) {

        } finally {
            if (httpget != null) {
                httpget.abort();
            }
            httpclient.getConnectionManager().shutdown();
        }
        JSONObject jsonObject = JSONObject.parseObject(new String(res, "utf-8"));
        System.out.println(jsonObject.toJSONString());
        openId = jsonObject.getString("openid");
        org.apache.http.client.HttpClient httpclient1 = new DefaultHttpClient();
        HttpGet httpget1 = new HttpGet();
        try {
            URL url1 = new URL("https://api.weixin.qq.com/sns/userinfo?access_token="+jsonObject.getString("access_token")
            +"&openid="+openId+"&lang=zh_CN");
            URI uri1 = new URI(url1.getProtocol(), url1.getHost(), url1.getPath(), url1.getQuery(), null);
            httpget1 = new HttpGet(uri1);
            HttpResponse response1 = null;
            response1 = httpclient1.execute(httpget1);
            res1 = IOUtils.toByteArray(response1.getEntity().getContent());
        } catch (Exception e) {

        } finally {
            if (httpget1 != null) {
                httpget1.abort();
            }
            httpclient1.getConnectionManager().shutdown();
        }
        JSONObject jsonObjects = JSONObject.parseObject(new String(res1, "utf-8"));
        String sessionKey=jsonObjects.getString("sessionKey");
        DtsUser user = userService.queryByOid(openId);
        if (user == null) {
            user = new DtsUser();
            user.setUsername(openId);
            user.setAvatar(jsonObjects.getString("headimgurl"));
            user.setNickname(jsonObjects.getString("nickname"));
            user.setCountry(jsonObjects.getString("country"));
            user.setProvince(jsonObjects.getString("province"));
            user.setCity(jsonObjects.getString("city"));
            user.setGender(jsonObjects.getByte("sex"));

            user.setPassword(openId);
            user.setWeixinOpenid(openId);
            user.setUserLevel((byte) 0);
            user.setStatus((byte) 0);
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtils.client(request));
            userService.add(user);
        } else {
            user.setCountry(jsonObjects.getString("country"));
            user.setProvince(jsonObjects.getString("province"));
            user.setCity(jsonObjects.getString("city"));
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtils.client(request));
            if (userService.updateById(user) == 0) {
                return ResponseUtils.updatedDataFailed();
            }
        }
        // token
        UserToken userToken = null;
        try {
            userToken = UserTokenManager.generateToken(user.getId(), sessionKey);
        } catch (Exception e) {
            logger.error("微信登录失败,生成token失败：{}", user.getId());
            e.printStackTrace();
            return ResponseUtils.fail();
        }
        Map<Object, Object> result = new HashMap<Object, Object>();
        result.put("token", userToken.getToken());
        result.put("tokenExpire", userToken.getExpireTime().toString());
        userInfo.setUserId(user.getId());
        try {
            String registerDate = DateTimeFormatter.ofPattern("yyyy-MM-dd")
                    .format(user.getAddTime() != null ? user.getAddTime() : LocalDateTime.now());
            userInfo.setRegisterDate(registerDate);
            userInfo.setStatus(user.getStatus());
            userInfo.setUserLevel(user.getUserLevel());// 用户层级
            userInfo.setUserLevelDesc(UserTypeEnum.getInstance(user.getUserLevel()).getDesc());// 用户层级描述
            userInfo.setWeixinOpenid(user.getWeixinOpenid());
        } catch (Exception e) {
            logger.error("微信登录：设置用户指定信息出错：" + e.getMessage());
            e.printStackTrace();
        }
        userInfo.setGender(user.getGender());
        userInfo.setNickName(user.getNickname());
        userInfo.setAvatarUrl(user.getAvatar());
        result.put("userInfo", userInfo);
        return ResponseUtils.ok(result);

    }
    @PostMapping("login_by_weixin")
    @ApiOperation(value = "微信小程序登录")
    public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {
        String code = wxLoginInfo.getCode();
        UserInfo userInfo = wxLoginInfo.getUserInfo();
        if (code == null || userInfo == null) {
            return ResponseUtils.badArgument();
        }

        Integer shareUserId = wxLoginInfo.getShareUserId();
        String sessionKey = null;
        String openId = null;
        try {
            WxMaJscode2SessionResult result = wxService.getUserService().getSessionInfo(code);
            sessionKey = result.getSessionKey();
            openId = result.getOpenid();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (sessionKey == null || openId == null) {
            logger.error("微信登录,调用官方接口失败：{}", code);
            return ResponseUtils.fail();
        }

        DtsUser user = userService.queryByOid(openId);

        if (user == null) {
            user = new DtsUser();
            user.setUsername(openId);
            user.setPassword(openId);
            user.setWeixinOpenid(openId);
            user.setAvatar(userInfo.getAvatarUrl());
            user.setNickname(userInfo.getNickName());
            user.setGender(userInfo.getGender());
            user.setUserLevel((byte) 0);
            user.setStatus((byte) 0);
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtils.client(request));
            user.setShareUserId(shareUserId);

            /**
             * 如果是变动代理模式，且不是代理推广的情况下，用户默认成为代理
             * 如果无shareUserId，或者为系统指定的默认用户 1 视为非代理用户的推广
             */
            if (SystemConfig.frequentAgencyModel() && (shareUserId == null || shareUserId < 2)) {
                user.setUserLevel((byte) 2);//成为区域代理
            }
            userService.add(user);

            /**
             * 如果是变动代理模式，且不是代理推广的情况下，用户需要设置代理账户,且默认已审批
             * 如果无shareUserId，或者为系统指定的默认用户 1 视为非代理用户的推广
             */
            if (SystemConfig.frequentAgencyModel() && (shareUserId == null || shareUserId < 2)) {
                DtsUserAccount userAccount = new DtsUserAccount();
                userAccount.setRemainAmount(new BigDecimal(0));
                userAccount.setSettlementRate(5);//默认5%的比例
                userAccount.setStatus((byte) 1);//生效
                userAccount.setTotalAmount(new BigDecimal(0));
                userAccount.setUserId(user.getId());
                /*
                 * 生成代理用户独有分享的二维码需要小程序已经上线，所以未上线小程序这里调用会异常
                 * 建议通过后台参数控制，因为定制用户对这里的特殊性要求，本程序暂不做调整
                 */
                String shareUrl = qCodeService.createShareUserImage(user.getId());
                userAccount.setShareUrl(shareUrl);

                userAccount.setModifyTime(LocalDateTime.now());
                accountService.add(userAccount);
            }

            // 新用户发送注册优惠券
            couponAssignService.assignForRegister(user.getId());
        } else {
            /**
             * 如果是变动代理模式，且不是代理用户登录,如果是有推广人，则变成推广人的下级
             * 如果无shareUserId，或者为系统指定的默认用户 1 视为非代理用户的推广
             */
            if (SystemConfig.frequentAgencyModel() && user.getUserLevel().intValue() != 2 && shareUserId != null && shareUserId > 1) {
                user.setShareUserId(shareUserId);
            }
            user.setLastLoginTime(LocalDateTime.now());
            user.setLastLoginIp(IpUtils.client(request));
            if (userService.updateById(user) == 0) {
                return ResponseUtils.updatedDataFailed();
            }
        }

        // token
        UserToken userToken = null;
        try {
            userToken = UserTokenManager.generateToken(user.getId(), sessionKey);
        } catch (Exception e) {
            logger.error("微信登录失败,生成token失败：{}", user.getId());
            e.printStackTrace();
            return ResponseUtils.fail();
        }

        Map<Object, Object> result = new HashMap<Object, Object>();
        result.put("token", userToken.getToken());
        result.put("tokenExpire", userToken.getExpireTime().toString());
        userInfo.setUserId(user.getId());
        if (!StringUtils.isEmpty(user.getMobile())) {// 手机号存在则设置
            userInfo.setPhone(user.getMobile());
        }
        try {
            String registerDate = DateTimeFormatter.ofPattern("yyyy-MM-dd")
                    .format(user.getAddTime() != null ? user.getAddTime() : LocalDateTime.now());
            userInfo.setRegisterDate(registerDate);
            userInfo.setStatus(user.getStatus());
            userInfo.setUserLevel(user.getUserLevel());// 用户层级
            userInfo.setUserLevelDesc(UserTypeEnum.getInstance(user.getUserLevel()).getDesc());// 用户层级描述
            userInfo.setWeixinOpenid(user.getWeixinOpenid());
        } catch (Exception e) {
            logger.error("微信登录：设置用户指定信息出错：" + e.getMessage());
            e.printStackTrace();
        }
        result.put("userInfo", userInfo);
        return ResponseUtils.ok(result);
    }

    /**
     * 请求验证码
     *
     * @param body 手机号码{mobile}
     * @return
     */
    @PostMapping("regCaptcha")
    @ApiOperation(value = "请求验证码")
    @WebLog(description = "请求验证码")
    public Object registerCaptcha(@ApiParam(value = "{mobile:xxx}") @RequestBody String body) {
        String phoneNumber = JacksonUtil.parseString(body, "mobile");
        if (StringUtils.isEmpty(phoneNumber)) {
            return ResponseUtils.badArgument();
        }
        if (!RegexUtils.isMobileExact(phoneNumber)) {
            return ResponseUtils.badArgumentValue();
        }

        if (!notifyService.isSmsEnable()) {
            logger.error("请求验证码出错:{}", AUTH_CAPTCHA_UNSUPPORT.desc());
            return WxResponseUtils.fail(AUTH_CAPTCHA_UNSUPPORT);
        }
        String code = CharUtils.getRandomNum(6);
        SmsResult smsResult = notifyService.notifySmsTemplate(phoneNumber, NotifyType.CAPTCHA, new String[]{code, "1"});
        if (smsResult != null) {
            logger.info("*****腾讯云短信发送->请求验证码，短信发送结果：{}", JSONObject.toJSONString(smsResult));
        }

        boolean successful = CaptchaCodeManager.addToRedisCache(phoneNumber, code, 1);
        if (!successful) {
            logger.error("请求验证码出错:{}", AUTH_CAPTCHA_FREQUENCY.desc());
            return WxResponseUtils.fail(AUTH_CAPTCHA_FREQUENCY);
        }
        return ResponseUtils.ok();
    }

    /**
     * 账号注册
     *
     * @param body    请求内容 { username: xxx, password: xxx, mobile: xxx code: xxx }
     *                其中code是手机验证码，目前还不支持手机短信验证码
     * @param request 请求对象
     * @return 登录结果 成功则 { errno: 0, errmsg: '成功', data: { token: xxx, tokenExpire:
     * xxx, userInfo: xxx } } 失败则 { errno: XXX, errmsg: XXX }
     */
    @PostMapping("register")
    @ApiOperation(value = "账号注册")
    public Object register(@ApiParam(value = "{ username: xxx, password: xxx, mobile: xxx code: xxx }") @RequestBody String body, HttpServletRequest request) {
        String username = JacksonUtil.parseString(body, "username");
        String password = JacksonUtil.parseString(body, "password");
        String mobile = JacksonUtil.parseString(body, "mobile");
        String code = JacksonUtil.parseString(body, "code");
        String wxCode = JacksonUtil.parseString(body, "wxCode");

        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || StringUtils.isEmpty(mobile)
                || StringUtils.isEmpty(wxCode) || StringUtils.isEmpty(code)) {
            return ResponseUtils.badArgument();
        }

        List<DtsUser> userList = userService.queryByUsername(username);
        if (userList.size() > 0) {
            logger.error("请求账号注册出错:{}", AUTH_NAME_REGISTERED.desc());
            return WxResponseUtils.fail(AUTH_NAME_REGISTERED);
        }

        userList = userService.queryByMobile(mobile);
        if (userList.size() > 0) {
            logger.error("请求账号注册出错:{}", AUTH_MOBILE_REGISTERED.desc());
            return WxResponseUtils.fail(AUTH_MOBILE_REGISTERED);
        }
        if (!RegexUtils.isMobileExact(mobile)) {
            logger.error("请求账号注册出错:{}", AUTH_INVALID_MOBILE.desc());
            return WxResponseUtils.fail(AUTH_INVALID_MOBILE);
        }

        // 判断验证码是否正确
        String cacheCode = CaptchaCodeManager.getRedisCachedCaptcha(mobile);
        if (cacheCode == null || cacheCode.isEmpty() || !cacheCode.equals(code)) {
            logger.error("请求账号注册出错:{}", AUTH_CAPTCHA_UNMATCH.desc());
            return WxResponseUtils.fail(AUTH_CAPTCHA_UNMATCH);
        }

        String openId = null;
        try {
            WxMaJscode2SessionResult result = wxService.getUserService().getSessionInfo(wxCode);
            openId = result.getOpenid();
        } catch (Exception e) {
            logger.error("请求账号注册出错:{}", AUTH_OPENID_UNACCESS.desc());
            e.printStackTrace();
            return WxResponseUtils.fail(AUTH_OPENID_UNACCESS);
        }
        userList = userService.queryByOpenid(openId);
        if (userList.size() > 1) {
            return ResponseUtils.serious();
        }
        if (userList.size() == 1) {
            DtsUser checkUser = userList.get(0);
            String checkUsername = checkUser.getUsername();
            String checkPassword = checkUser.getPassword();
            if (!checkUsername.equals(openId) || !checkPassword.equals(openId)) {
                logger.error("请求账号注册出错:{}", AUTH_OPENID_BINDED.desc());
                return WxResponseUtils.fail(AUTH_OPENID_BINDED);
            }
        }

        DtsUser user = null;
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodedPassword = encoder.encode(password);
        user = new DtsUser();
        user.setUsername(username);
        user.setPassword(encodedPassword);
        user.setMobile(mobile);
        user.setWeixinOpenid(openId);
        user.setAvatar(CommConsts.DEFAULT_AVATAR);
        user.setNickname(username);
        user.setGender((byte) 0);
        user.setUserLevel((byte) 0);
        user.setStatus((byte) 0);
        user.setLastLoginTime(LocalDateTime.now());
        user.setLastLoginIp(IpUtils.client(request));
        userService.add(user);

        // 给新用户发送注册优惠券
        try {
            couponAssignService.assignForRegister(user.getId());
        } catch (Exception e) {
            logger.error("账号注册失败,给新用户发送注册优惠券失败：{}", user.getId());
            e.printStackTrace();
            return ResponseUtils.fail();
        }

        // userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setNickName(username);
        userInfo.setAvatarUrl(user.getAvatar());

        // token
        UserToken userToken = null;
        try {
            userToken = UserTokenManager.generateToken(user.getId(), null);
        } catch (Exception e) {
            logger.error("账号注册失败,生成token失败：{}", user.getId());
            e.printStackTrace();
            return ResponseUtils.fail();
        }
        return getUserAndTokenInfo(userInfo, userToken);
    }

    /**
     * 账号密码重置
     *
     * @param body    请求内容 { password: xxx, mobile: xxx code: xxx }
     *                其中code是手机验证码，目前还不支持手机短信验证码
     * @param request 请求对象
     * @return 登录结果 成功则 { errno: 0, errmsg: '成功' } 失败则 { errno: XXX, errmsg: XXX }
     */
    @PostMapping("reset")
    @ApiOperation(value = "账号密码重置")
    public Object reset(@ApiParam(value = "{ password: xxx, mobile: xxx code: xxx }") @RequestBody String body, HttpServletRequest request) {
        String password = JacksonUtil.parseString(body, "password");
        String mobile = JacksonUtil.parseString(body, "mobile");
        String code = JacksonUtil.parseString(body, "code");

        if (mobile == null || code == null || password == null) {
            return ResponseUtils.badArgument();
        }

        // 判断验证码是否正确
        String cacheCode = CaptchaCodeManager.getRedisCachedCaptcha(mobile);
        if (cacheCode == null || cacheCode.isEmpty() || !cacheCode.equals(code)) {
            logger.error("账号密码重置出错:{}", AUTH_CAPTCHA_UNMATCH.desc());
            return WxResponseUtils.fail(AUTH_CAPTCHA_UNMATCH);
        }

        List<DtsUser> userList = userService.queryByMobile(mobile);

        DtsUser user = null;
        if (userList.size() > 1) {
            logger.error("账号密码重置出错,账户不唯一,查询手机号:{}", mobile);
            return ResponseUtils.serious();
        } else if (userList.size() == 0) {
            logger.error("账号密码重置出错,账户不存在,查询手机号:{},{}", mobile, AUTH_MOBILE_UNREGISTERED.desc());
            return WxResponseUtils.fail(AUTH_MOBILE_UNREGISTERED);
        } else {
            user = userList.get(0);
        }

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodedPassword = encoder.encode(password);
        user.setPassword(encodedPassword);

        if (userService.updateById(user) == 0) {
            logger.error("账号密码重置更新用户信息出错,id：{}", user.getId());
            return ResponseUtils.updatedDataFailed();
        }
        return ResponseUtils.ok();
    }

    /**
     * 绑定手机号码
     *
     * @param userId
     * @param body
     * @return
     */
    @PostMapping("bindPhone")
    @ApiOperation(value = "绑定手机号码")
    @WebLog(description = "绑定手机号码")
    public Object bindPhone(@LoginUser Integer userId, @ApiParam(value = "{encryptedData:xxx,iv:xxx}") @RequestBody String body) {
        String sessionKey = UserTokenManager.getSessionKey(userId);
        String encryptedData = JacksonUtil.parseString(body, "encryptedData");
        String iv = JacksonUtil.parseString(body, "iv");
        WxMaPhoneNumberInfo phoneNumberInfo = null;
        try {
            phoneNumberInfo = wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
        } catch (Exception e) {
            logger.error("绑定手机号码失败,获取微信绑定的手机号码出错：{}", body);
            e.printStackTrace();
            return ResponseUtils.fail();
        }
        String phone = phoneNumberInfo.getPhoneNumber();
        DtsUser user = userService.findById(userId);
        user.setMobile(phone);
        if (userService.updateById(user) == 0) {
            logger.error("绑定手机号码,更新用户信息出错,id：{}", user.getId());
            return ResponseUtils.updatedDataFailed();
        }
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("phone", phone);
        return ResponseUtils.ok(data);
    }

    /**
     * 注销登录
     *
     * @param userId
     * @return
     */
    @PostMapping("logout")
    @ApiOperation(value = "注销登录")
    @WebLog(description = "注销登录")
    public Object logout(@LoginUser Integer userId) {
        if (userId == null) {
            return ResponseUtils.unlogin();
        }
        try {
            UserTokenManager.removeToken(userId);
        } catch (Exception e) {
            logger.error("注销登录出错：userId:{}", userId);
            e.printStackTrace();
            return ResponseUtils.fail();
        }
        return ResponseUtils.ok();
    }

    /**
     * 检查是否登录
     *
     * @param userId
     * @return
     */
    @PostMapping("checkLogin")
    @ApiOperation(value = "检查是否登录")
    @WebLog(description = "检查是否登录")
    public Object checkLogin(@LoginUser Integer userId) {
        if (userId == null) {
            logger.info("【请求结束】检查用户-未登录!");
            return ResponseUtils.unlogin();
        } else {
            return ResponseUtils.ok();
        }
    }
}
